<%@page import="java.util.*"%>
<%@page import="tmanager.*"%>
<%@ page import="java.sql.*" %>

<%!    
    String stringaConnessione = "jdbc:mysql://localhost:3306/tmanager";
    String utenteSQL = "root";
    String passwordSQL = "";
    String insertStudente = "insert into studente (matricola, nome, cognome, email, "
            + "password, relatore, statotesi, titolo, corsotesi, tipologiatesi, "
            + "tipolaurea) values (?,?,?,?,?,?,?,?,?,?,?)";
    String insertProfessore = "insert into professore (identificativo, nome, "
            + "cognome, email, password, primoaccesso) values (?,?,?,?,?,?)";
    String insertMessaggio = "insert into messaggio (idstudente, idprofessore, "
            + "mittente, destinatario, messaggioletto, oggetto, contenuto, "
            + "timestamp, rispostainviata) values (?,?,?,?,?,?,?,?,?)";
    String insertFile = "insert into file (timestamp, nomefile, tmpnome, tipofile, "
            + "size, idstudente, idprofessore, proprietario, contenuto) values (?,?,?,?,?,?,?,?,?)";
    String trovaFile = "select timestamp, nomefile, tmpnome, tipofile, "
            + "size, idstudente, idprofessore, proprietario, contenuto from file where timestamp=?";
    String trovaFileStud = "select timestamp, nomefile, tmpnome, tipofile, "
            + "size, idstudente, idprofessore, proprietario from file where idstudente=? order by timestamp desc";
    String headerMessaggi = "select idstudente, idprofessore, mittente, "
            + "destinatario, messaggioletto, oggetto, contenuto, "
            + "timestamp, rispostainviata from messaggio ";
    String messaggiRicevuti = headerMessaggi + " where idstudente=? and idprofessore=? and destinatario=? order by timestamp desc";
    String messaggiInviati = headerMessaggi + " where idstudente=? and idprofessore=? and mittente=? order by timestamp desc";
    String sqlProfessore = "select identificativo, nome, cognome, email, password from professore ";
    String sqlDatiProfessore = sqlProfessore + " where identificativo=?";
    String sqlStudente = "select matricola, nome, cognome, email, password, relatore, statotesi, titolo, corsotesi, tipologiatesi, tipolaurea from studente ";
    String sqlDatiStudente = sqlStudente + " where matricola=?";
    String messaggioFromId = "select idstudente, idprofessore, mittente, "
            + "destinatario, messaggioletto, oggetto, contenuto, "
            + "timestamp, rispostainviata from messaggio where timestamp=?";
    String tesistiProf = "select matricola, nome, cognome from studente where relatore=?";
    String emailProfessore = "select * from professore where email=?";
    String emailStudente = "select * from studente where email=?";
    String updateMailPassStudente = "update studente set email=?, password=? where matricola=?";
    String updateStatoStudente = "update studente set statotesi=?, titolo=?, corsotesi=?, tipologiatesi=?, tipolaurea=? where matricola=?";
    String updateMailPassProfessore = "update professore set email=?, password=? where identificativo=?";
    String messaggiRicevutiProf = headerMessaggi + " where idprofessore=? and destinatario=? order by timestamp desc";
    String messaggiInviatiProf = headerMessaggi + " where idprofessore=? and mittente=? order by timestamp desc";
    String messaggioLetto = "update messaggio set messaggioletto=? where timestamp=?";
    String messaggioReply = "update messaggio set rispostainviata=? where timestamp=?";
    String messaggiNonLettiProf = headerMessaggi + " where idprofessore=? and destinatario=? and messaggioletto=false order by timestamp desc";
    String sqlLoginStudente = sqlStudente + " where matricola=? and password=?";
    String sqlLoginProf = sqlProfessore + " where identificativo=? and password=?";
    String nomeStudFromId = "select nome, cognome from studente where matricola=?";
    String nomeProfFromId = "select nome, cognome from professore where identificativo=?";
    String ricercaMessaggi = "select idstudente, idprofessore, mittente, destinatario, "
            + "messaggioletto, oggetto, contenuto, timestamp, rispostainviata, "
            + "match(oggetto, contenuto) against(? IN BOOLEAN MODE) as rilevanza "
            + "from messaggio where idstudente=? and idprofessore=? ";
    String ricercaMessaggiRicevuti = ricercaMessaggi
            + " and destinatario=? and match(oggetto, contenuto) against(? IN BOOLEAN MODE) order by rilevanza desc, timestamp desc";
    String ricercaMessaggiInviati = ricercaMessaggi
            + " and mittente=? and match(oggetto, contenuto) against(? IN BOOLEAN MODE) order by rilevanza desc, timestamp desc";
    String ricercaInTuttiMessaggi = ricercaMessaggi
            + " and match(oggetto, contenuto) against(? IN BOOLEAN MODE) order by rilevanza desc, timestamp desc";

%>

<%
    try {
        Class.forName("com.mysql.jdbc.Driver");
    } catch (ClassNotFoundException e) {
        response.sendRedirect("errore.jsp");
        return;
    }
%>

<%! //Recupero dal database il messaggio a partire dal suo id
    Messaggio messaggioFromId(String query, long idMessaggio) throws SQLException {
        Messaggio messaggioReplied = null;
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(query);

            ps.setLong(1, idMessaggio);
            ResultSet r = ps.executeQuery();

            if (r.next()) {
                messaggioReplied = new Messaggio();
                messaggioReplied.setIdStudente(r.getInt(1));
                messaggioReplied.setIdProfessore(r.getInt(2));
                messaggioReplied.setMittente(r.getString(3));
                messaggioReplied.setDestinatario(r.getString(4));
                messaggioReplied.setMessaggioLetto(r.getBoolean(5));
                messaggioReplied.setOggetto(r.getString(6));
                messaggioReplied.setContenuto(r.getString(7));
                messaggioReplied.setTimestamp(r.getLong(8));
                messaggioReplied.setRispostaInviata(r.getBoolean(9));
            }

            r.close();
            ps.close();
            c.close();
            if (messaggioReplied == null) {
                throw new SQLException();
            }
            return messaggioReplied;
        } catch (SQLException e) {
            throw e;
        }
    }

    //Recupero dal database tutti i messaggi di uno studente
    Vector<Messaggio> messaggiProdottiStudente(String query, Studente s) throws SQLException {
        Vector<Messaggio> messaggi = new Vector<Messaggio>();
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);

            PreparedStatement ps = c.prepareStatement(query);
            ps.setInt(1, s.getMatricola());
            ps.setInt(2, s.getRelatore());
            ps.setString(3, s.getNome() + " " + s.getCognome());
            ResultSet r = ps.executeQuery();

            while (r.next()) {
                Messaggio m = new Messaggio();
                m.setIdStudente(r.getInt(1));
                m.setIdProfessore(r.getInt(2));
                m.setMittente(r.getString(3));
                m.setDestinatario(r.getString(4));
                m.setMessaggioLetto(r.getBoolean(5));
                m.setOggetto(r.getString(6));
                m.setContenuto(r.getString(7));
                m.setTimestamp(r.getLong(8));
                m.setRispostaInviata(r.getBoolean(9));

                messaggi.add(m);
            }
            r.close();
            ps.close();
            c.close();
            return messaggi;
        } catch (SQLException e) {
            log("Errore: errore durante il recupero dei dati del messaggio per studente con id: " + s.getMatricola() + ".\n" + e.getMessage());
            throw e;
        }
    }

    //Recupero dal database i messaggi di un professore
    Vector<Messaggio> messaggiProdottiProfessore(String query, Professore p, int idStudente) throws SQLException {
        Vector<Messaggio> messaggi = new Vector<Messaggio>();
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);

            PreparedStatement ps = c.prepareStatement(query);
            if (idStudente == -1) {
                ps.setInt(1, p.getIdentificativo());
                ps.setString(2, p.getNome() + " " + p.getCognome());
            } else {
                ps.setInt(1, idStudente);
                ps.setInt(2, p.getIdentificativo());
                ps.setString(3, p.getNome() + " " + p.getCognome());
            }


            ResultSet r = ps.executeQuery();

            while (r.next()) {
                Messaggio m = new Messaggio();
                m.setIdStudente(r.getInt(1));
                m.setIdProfessore(r.getInt(2));
                m.setMittente(r.getString(3));
                m.setDestinatario(r.getString(4));
                m.setMessaggioLetto(r.getBoolean(5));
                m.setOggetto(r.getString(6));
                m.setContenuto(r.getString(7));
                m.setTimestamp(r.getLong(8));
                m.setRispostaInviata(r.getBoolean(9));

                messaggi.add(m);
            }
            r.close();
            ps.close();
            c.close();
            return messaggi;
        } catch (SQLException e) {
            throw e;
        }
    }

    //Aggiorna il metadato risposta inviata del corrispondente messaggio
    int registraReplyLetto(String query, long idMessaggio) throws SQLException {
        int tupleInserite;

        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(query);
            ps.setBoolean(1, true);
            ps.setLong(2, idMessaggio);
            tupleInserite = ps.executeUpdate();
            ps.close();
            c.close();
            return tupleInserite;
        } catch (SQLException e) {
            throw e;
        }
    }

    //Salvo nel database il messaggio m
    int registraMessaggio(String query, Messaggio m) throws SQLException {
        int tupleInserite;

        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(query);
            ps.setInt(1, m.getIdStudente());
            ps.setInt(2, m.getIdProfessore());
            ps.setString(3, m.getMittente());
            ps.setString(4, m.getDestinatario());
            ps.setBoolean(5, m.getMessaggioLetto());
            ps.setString(6, m.getOggetto());
            ps.setString(7, m.getContenuto());
            ps.setLong(8, m.getTime());
            ps.setBoolean(9, m.getRispostaInviata());

            tupleInserite = ps.executeUpdate();
            ps.close();
            c.close();
            return tupleInserite;
        } catch (SQLException e) {
            throw e;
        }
    }

    //Recupero dal databese lo studente a partire dalla sua matricola
    Studente getStudenteFromDB(String query, int matricola) throws SQLException {
        Studente stud = null;
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(query);
            ps.setInt(1, matricola);
            ResultSet r = ps.executeQuery();
            if (r.next()) {
                stud = new Studente();
                stud.setMatricola(r.getInt(1));
                stud.setNome(r.getString(2));
                stud.setCognome(r.getString(3));
                stud.setEmail(r.getString(4));
                stud.setPassword(r.getString(5));
                stud.setRelatore(r.getInt(6));
                stud.setStatoProgettoTesi(r.getString(7));
                stud.setTitoloTesi(r.getString(8));
                stud.setCorsoTesi(r.getString(9));
                stud.setTipologiaTesi(r.getString(10));
                stud.setTipoLaurea(r.getString(11));
            }
            r.close();
            ps.close();
            c.close();

            return stud;
        } catch (SQLException e) {
            log("Errore: errore durante il recupero dei dati dello studente con matricola: " + matricola + ".\n" + e.getMessage());
            throw e;
        }
    }

    //Recupero dal database il professore a partire dalla sua matricola
    Professore getProfessoreFromDB(int id) throws SQLException {
        Professore prof = null;
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(sqlDatiProfessore);
            ps.setInt(1, id);
            ResultSet r = ps.executeQuery();

            if (r.next()) {
                prof = new Professore();
                prof.setIdentificativo(r.getInt(1));
                prof.setNome(r.getString(2));
                prof.setCognome(r.getString(3));
                prof.setEmail(r.getString(4));
                prof.setPassword(r.getString(5));
            }
            r.close();
            ps.close();
            c.close();

            return prof;
        } catch (SQLException e) {
            log("Errore: errore durante il recupero dei dati del professore con id: " + id + ".\n" + e.getMessage());
            throw e;
        }
    }

    //Recupero dal database lo sudente controllando matricola e password
    Studente loginStudente(int matricola, String password) throws SQLException {
        Studente stud = null;

        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(sqlLoginStudente);
            ps.setInt(1, matricola);
            ps.setString(2, Utility.getMD5(password));
            ResultSet r = ps.executeQuery();

            if (r.next()) {
                stud = new Studente();
                stud.setMatricola(r.getInt(1));
                stud.setNome(r.getString(2));
                stud.setCognome(r.getString(3));
                stud.setEmail(r.getString(4));
                stud.setPassword(r.getString(5));
                stud.setRelatore(r.getInt(6));
                stud.setStatoProgettoTesi(r.getString(7));
                stud.setTitoloTesi(r.getString(8));
                stud.setCorsoTesi(r.getString(9));
                stud.setTipologiaTesi(r.getString(10));
                stud.setTipoLaurea(r.getString(11));
            }
            r.close();
            ps.close();
            c.close();

            return stud;
        } catch (SQLException e) {
            log("Errore: errore durante il login dello studente con matricola: " + matricola + ".\n" + e.getMessage());
            throw e;
        }
    }

    //Recupero dal database il professore controllando matricola e password
    Professore loginProfessore(int id, String password) throws SQLException {
        Professore prof = null;

        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(sqlLoginProf);
            ps.setInt(1, id);
            ps.setString(2, Utility.getMD5(password));
            ResultSet r = ps.executeQuery();

            if (r.next()) {
                prof = new Professore();
                prof.setIdentificativo(r.getInt(1));
                prof.setNome(r.getString(2));
                prof.setCognome(r.getString(3));
                prof.setEmail(r.getString(4));
                prof.setPassword(r.getString(5));
            }
            r.close();
            ps.close();
            c.close();

            return prof;
        } catch (SQLException e) {
            log("Login.jsp: connessione al database tmanger fallita.");
            throw e;
        }
    }

    //Recupero dal database la lista dei tesisti a partire dall'id del professore
    Vector<Studente> getStudentiByRelatore(int id) throws SQLException {
        Vector<Studente> tesisti = new Vector<Studente>();
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(tesistiProf);
            ps.setInt(1, id);
            ResultSet r = ps.executeQuery();

            while (r.next()) {
                Studente s = new Studente();
                s.setMatricola(r.getInt(1));
                s.setNome(r.getString(2));
                s.setCognome(r.getString(3));
                tesisti.add(s);
            }
            r.close();
            ps.close();
            c.close();

            return tesisti;
        } catch (SQLException e) {
            log("Errore: errore durante il recupero dei dati relativi ai tesiti associati al docente con id: " + id + ".\n" + e.getMessage());
            throw e;
        }
    }

    //Recupero dal database i file condivisi da uno studente con il suo relatore
    Vector<tmanager.File> getFilesStudente(int idStudente) throws SQLException {
        Vector<tmanager.File> files = new Vector<tmanager.File>();
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(trovaFileStud);
            ps.setInt(1, idStudente);
            ResultSet r = ps.executeQuery();
            while (r.next()) {
                tmanager.File f = new tmanager.File();
                f.setTimestamp(r.getLong(1));
                f.setNomeFile(r.getString(2));
                f.setTmpNome(r.getString(3));
                f.setTipoFile(r.getString(4));
                f.setSize(r.getLong(5));
                f.setIdStudente(r.getInt(6));
                f.setIdProfessore(r.getInt(7));
                f.setProprietario(r.getString(8));

                files.add(f);
            }
            r.close();
            ps.close();
            c.close();

            return files;
        } catch (SQLException e) {
            log("Errore: errore durante il recupero dei file relativi allo studente con id: " + idStudente + ".\n" + e.getMessage());
            throw e;
        }
    }

    //Recupero i messaggi dello studente che matchano con la keyword
    Vector<Messaggio> ricercaInMessaggiStudente(String query, Studente s, String keyword) throws SQLException {
        Vector<Messaggio> messaggi = new Vector<Messaggio>();
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);

            PreparedStatement ps = c.prepareStatement(query);
            ps.setString(1, keyword);
            ps.setInt(2, s.getMatricola());
            ps.setInt(3, s.getRelatore());
            ps.setString(4, s.getNome() + " " + s.getCognome());
            ps.setString(5, keyword);
            ResultSet r = ps.executeQuery();

            while (r.next()) {
                Messaggio m = new Messaggio();
                m.setIdStudente(r.getInt(1));
                m.setIdProfessore(r.getInt(2));
                m.setMittente(r.getString(3));
                m.setDestinatario(r.getString(4));
                m.setMessaggioLetto(r.getBoolean(5));
                m.setOggetto(r.getString(6));
                m.setContenuto(r.getString(7));
                m.setTimestamp(r.getLong(8));
                m.setRispostaInviata(r.getBoolean(9));

                messaggi.add(m);
            }
            r.close();
            ps.close();
            c.close();
            return messaggi;
        } catch (SQLException e) {
            log("Errore: errore durante la ricerca nei messaggi dello studente con id: " + s.getMatricola() + ".\n" + e.getMessage());
            throw e;
        }
    }

    //Recupero i messaggi dello professore che matchano con la keyword
    Vector<Messaggio> ricercaInMessaggiProfessore(String query, Professore p, int idStudente, String keyword) throws SQLException {
        Vector<Messaggio> messaggi = new Vector<Messaggio>();
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);

            PreparedStatement ps = c.prepareStatement(query);
            ps.setString(1, keyword);
            ps.setInt(2, idStudente);
            ps.setInt(3, p.getIdentificativo());
            ps.setString(4, p.getNome() + " " + p.getCognome());
            ps.setString(5, keyword);

            ResultSet r = ps.executeQuery();

            while (r.next()) {
                Messaggio m = new Messaggio();
                m.setIdStudente(r.getInt(1));
                m.setIdProfessore(r.getInt(2));
                m.setMittente(r.getString(3));
                m.setDestinatario(r.getString(4));
                m.setMessaggioLetto(r.getBoolean(5));
                m.setOggetto(r.getString(6));
                m.setContenuto(r.getString(7));
                m.setTimestamp(r.getLong(8));
                m.setRispostaInviata(r.getBoolean(9));

                messaggi.add(m);
            }
            r.close();
            ps.close();
            c.close();
            return messaggi;
        } catch (SQLException e) {
            throw e;
        }
    }

    //Recupero tutti i messaggi che matchano con la keyword
    Vector<Messaggio> ricercaInTuttiMessaggi(String query, int idStudente, int idProfessore, String keyword) throws SQLException {
        Vector<Messaggio> messaggi = new Vector<Messaggio>();
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);

            PreparedStatement ps = c.prepareStatement(query);
            ps.setString(1, keyword);
            ps.setInt(2, idStudente);
            ps.setInt(3, idProfessore);
            ps.setString(4, keyword);

            ResultSet r = ps.executeQuery();

            while (r.next()) {
                Messaggio m = new Messaggio();
                m.setIdStudente(r.getInt(1));
                m.setIdProfessore(r.getInt(2));
                m.setMittente(r.getString(3));
                m.setDestinatario(r.getString(4));
                m.setMessaggioLetto(r.getBoolean(5));
                m.setOggetto(r.getString(6));
                m.setContenuto(r.getString(7));
                m.setTimestamp(r.getLong(8));
                m.setRispostaInviata(r.getBoolean(9));

                messaggi.add(m);
            }
            r.close();
            ps.close();
            c.close();
            return messaggi;
        } catch (SQLException e) {
            throw e;
        }
    }

    //Aggiorno lo stato dello studente sul database
    int updateStatoStudente(Studente stud) throws SQLException {
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(updateStatoStudente);
            ps.setString(1, stud.getStatoProgettoTesi());
            ps.setString(2, stud.getTitoloTesi());
            ps.setString(3, stud.getCorsoTesi());
            ps.setString(4, stud.getTipologiaTesi());
            ps.setString(5, stud.getTipoLaurea());
            ps.setInt(6, stud.getMatricola());
            return ps.executeUpdate();
        } catch (SQLException e) {
            throw e;
        }
    }

    //Aggiorno il profilo professore sul database
    int updateProfiloProfessore(Professore prof) throws SQLException {
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(updateMailPassProfessore);
            ps.setString(1, prof.getEmail());
            ps.setString(2, prof.getPassword());
            ps.setInt(3, prof.getIdentificativo());
            return ps.executeUpdate();
        } catch (SQLException e) {
            throw e;
        }
    }

    //Aggiorno il profilo studente sul database
    int updateProfiloStudente(Studente stud) throws SQLException {
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(updateMailPassStudente);
            ps.setString(1, stud.getEmail());
            ps.setString(2, stud.getPassword());
            ps.setInt(3, stud.getMatricola());
            return ps.executeUpdate();
        } catch (SQLException e) {
            throw e;
        }
    }

    //Creo nel database il profilo completo per un nuovo studente
    int insertStudente(Studente stud) throws SQLException {
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(insertStudente);
            ps.setInt(1, stud.getMatricola());
            ps.setString(2, stud.getNome());
            ps.setString(3, stud.getCognome());
            ps.setString(4, stud.getEmail());
            ps.setString(5, stud.getPassword());
            ps.setInt(6, stud.getRelatore());
            ps.setString(7, stud.getStatoProgettoTesi());
            ps.setString(8, stud.getTitoloTesi());
            ps.setString(9, stud.getCorsoTesi());
            ps.setString(10, stud.getTipologiaTesi());
            ps.setString(11, stud.getTipoLaurea());

            int tupleInserite = ps.executeUpdate();
            ps.close();
            c.close();
            return tupleInserite;
        } catch (SQLException e) {
            throw e;
        }
    }

    //Carico nel database il nuovo file
    boolean caricaFile(tmanager.File f, Blob blob) throws SQLException {
        try {
            Connection c = DriverManager.getConnection(stringaConnessione, utenteSQL, passwordSQL);
            PreparedStatement ps = c.prepareStatement(insertFile);
            ps.setLong(1, f.getTimestamp());
            ps.setString(2, f.getNomeFile());
            ps.setString(3, f.getTmpNome());
            ps.setString(4, f.getTipoFile());
            ps.setLong(5, f.getSize());
            ps.setInt(6, f.getIdStudente());
            ps.setInt(7, f.getIdProfessore());
            ps.setString(8, f.getProprietario());
            ps.setBlob(9, blob);
            int tupleInserite = ps.executeUpdate();
            ps.close();
            c.close();
            if (tupleInserite==-1){
                return false;
            }
            return true;

        } catch (SQLException e) {
            throw e;
        }
    }
%>